package dbexel.presentation.aat;

import static org.junit.Assert.*;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.gargoylesoftware.htmlunit.ConfirmHandler;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebAssert;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTable;
import com.gargoylesoftware.htmlunit.html.HtmlTextArea;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;

import dbexel.model.dao.JPATestTools;
import dbexel.model.dao.WorkSheetDao;
import dbexel.model.dao.WorkSheetDaoImpl;
import dbexel.model.mapping.AttributeValue;
import dbexel.model.mapping.WorkSheet;
import dbexel.model.mapping.WorkSheet_Attribute;
import dbexel.model.mapping.WorkSheet_Entry;
import dbexel.system.tools.DBExelTestTools;
import dbexel.system.tools.FileUtils;

public class WorkSheetAAT {
	private static WorkSheetDao wsDao = new WorkSheetDaoImpl();
	private static WebClient webClient;

	@BeforeClass
	public static void cleanSystem() {
		JPATestTools.cleanAllData();
	}
	
	@Before
	public void initSystem() {
		
		webClient = new WebClient();
	}

	@After
	public void cleanWindows() {
		JPATestTools.cleanAllData();
		webClient.closeAllWindows();
	}
	
	@Test
	public void testCreate1() throws FailingHttpStatusCodeException,
			MalformedURLException, IOException {

		// Get first page
		HtmlPage l_currentPage = (HtmlPage) webClient.getPage(new URL(FileUtils
				.fetchProperty("dbexel.testsite") + "/DBEXEL/"));

		WebAssert.assertLinkPresentWithText(l_currentPage, FileUtils
				.fetchProperty("dbexel.testsite.TestCreate.page1.txt1"));

		// Second page
		l_currentPage = l_currentPage
				.getAnchorByText(
						FileUtils
								.fetchProperty("dbexel.testsite.TestCreate.page1.txt1"))
				.click();
		HtmlForm l_form = l_currentPage.getFormByName("InitWorkSheetAction");
		WebAssert.assertInputContainsValue(l_currentPage, FileUtils
				.fetchProperty("dbexel.testsite.TestCreate.page2.input1"),
				"First Worksheet");

		// HtmlInput l_input1 =
		// l_form.getInputByName(FileUtils.fetchProperty("dbexel.testsite.TestCreate.page2.input1"));
		HtmlTextArea l_input2 = l_form.getTextAreaByName(FileUtils
				.fetchProperty("dbexel.testsite.TestCreate.page2.input2"));
		assertEquals("2A", "Hello cruel World", l_input2.getDefaultValue());

		// WebAssert.assertInputContainsValue(l_currentPage,
		// FileUtils.fetchProperty("dbexel.testsite.TestCreate.page2.input2"),
		// "Hello cruel World");

		HtmlSubmitInput l_submitButton = l_form.getInputByValue("Submit");

		l_currentPage = l_submitButton.click();

		// Checking the new page
		WebAssert.assertFormPresent(l_currentPage, "StoreInitWorkSheetAction");

		HtmlForm l_currentForm = l_currentPage
				.getFormByName("StoreInitWorkSheetAction");

		WebAssert
				.assertTextPresent(l_currentPage,
						"Please enter details for the data you entered for the worksheet");

		// Checking the correct division of the sentence
		WebAssert.assertInputContainsValue(l_currentPage, "attributeValues[0]",
				"Hello");
		WebAssert.assertInputContainsValue(l_currentPage, "attributeValues[1]",
				"cruel");
		WebAssert.assertInputContainsValue(l_currentPage, "attributeValues[2]",
				"World");

		// 8 Inputs
		// 6 normal ones
		// 1 submit button
		// 1 hidden
		assertEquals("Bad number of inputs", 6, DBExelTestTools
				.fetchVisibleInputFields(l_currentForm).size());

		assertEquals(
				"Bad number of header fields",
				DBExelTestTools.getInputsByNameStart(l_currentForm,
						"attributeNames[").size(),
				DBExelTestTools.getInputsByNameStart(l_currentForm,
						"attributeValues[").size());

		assertEquals(
				"Bad number of select fields",
				DBExelTestTools.getInputsByNameStart(l_currentForm,
						"attributeNames[").size(),
				DBExelTestTools.getSelectsByNameStart(l_currentForm,
						"cellAction").size());

		HtmlSelect l_selectItem = DBExelTestTools.getSelectsByNameStart(
				l_currentForm, "cellAction").get(1);

		assertEquals(6, l_selectItem.getOptionSize());

		assertEquals("Keep", l_selectItem.getDefaultValue());

		l_currentForm.setAttribute("attributeNames[0]", "A");
		l_currentForm.setAttribute("attributeNames[1]", "B");
		l_currentForm.setAttribute("attributeNames[2]", "C");

		l_currentPage = DBExelTestTools.getSubmitButton(l_currentForm).click();

		WebAssert.assertLinkPresentWithText(l_currentPage, "First Worksheet");

	}

	@Test
	public void testCreate2() throws FailingHttpStatusCodeException,
			MalformedURLException, IOException {

		// Get first page
		HtmlPage l_currentPage = (HtmlPage) webClient.getPage(new URL(FileUtils
				.fetchProperty("dbexel.testsite") + "/DBEXEL/"));

		// Second page
		l_currentPage = l_currentPage
				.getAnchorByText(
						FileUtils
								.fetchProperty("dbexel.testsite.TestCreate.page1.txt1"))
				.click();

		HtmlForm l_currentForm = l_currentPage
				.getFormByName("InitWorkSheetAction");

		String l_thisWorkSheet = "Loans WorkSheet";

		l_currentForm
				.getInputByName(
						FileUtils
								.fetchProperty("dbexel.testsite.TestCreate.page2.input1"))
				.setValueAttribute(l_thisWorkSheet);

		l_currentForm
				.getTextAreaByName(
						FileUtils
								.fetchProperty("dbexel.testsite.TestCreate.page2.input2"))
				.setText("Lended 5� to Johnathan on 15/10/2012");

		// Go to the next Page
		l_currentPage = DBExelTestTools.getSubmitButton(l_currentForm).click();

		l_currentForm = l_currentPage.getFormByName("StoreInitWorkSheetAction");

		assertEquals("1. Bad number of sentance divisions", 6, DBExelTestTools
				.getInputsByNameStart(l_currentForm, "attributeNames[").size());

		l_currentForm.getInputByName("attributeNames[0]")
				.setValueAttribute("A");
		l_currentForm.getInputByName("attributeNames[1]").setValueAttribute(
				"Amount");
		l_currentForm.getInputByName("attributeNames[2]")
				.setValueAttribute("C");
		l_currentForm.getInputByName("attributeNames[3]").setValueAttribute(
				"Person");
		l_currentForm.getInputByName("attributeNames[4]")
				.setValueAttribute("C");
		l_currentForm.getInputByName("attributeNames[5]").setValueAttribute(
				"Loan Date");

		l_currentForm.getSelectByName("cellActions[0]").setSelectedAttribute(
				"Delete", true);
		l_currentForm.getSelectByName("cellActions[2]").setSelectedAttribute(
				"Delete", true);
		l_currentForm.getSelectByName("cellActions[4]").setSelectedAttribute(
				"Delete", true);

		// Go to the next page
		l_currentPage = DBExelTestTools.getSubmitButton(l_currentForm).click();

		// Enter New Worksheet
		l_currentPage = l_currentPage.getAnchorByText(l_thisWorkSheet).click();

		WebAssert.assertTitleEquals(l_currentPage, "Work Sheet "
				+ l_thisWorkSheet + " Details");
		WebAssert.assertTextPresent(l_currentPage, "Work Sheet "
				+ l_thisWorkSheet);
		final HtmlTable l_currentTable = (HtmlTable) l_currentPage
				.getElementById("workSheetContentTable");

		// We have one row per entry + 1 column for headers
		assertEquals("1. Wrong number of rows", 2, l_currentTable.getRowCount());

		// We have one column per attribute + 1 column for actions
		assertEquals("1. wrong number of columns", 4, l_currentTable.getRow(0)
				.getCells().size());

	}

	@Test
	public void testDeleteWorkSheet() throws FailingHttpStatusCodeException,
			MalformedURLException, IOException {

		// Go to start page
		HtmlPage l_currentPage = (HtmlPage) webClient.getPage(new URL(FileUtils
				.fetchProperty("dbexel.testsite") + "/DBEXEL/"));

		WorkSheet l_workSheet = fetchTestWorkSheet("testDeleteWorkSheet");

		wsDao.createWorkSheet(l_workSheet);

		// Go to start page
		l_currentPage = (HtmlPage) webClient.getPage(new URL(FileUtils
				.fetchProperty("dbexel.testsite") + "/DBEXEL/"));

		// select New Worksheet
		l_currentPage = l_currentPage.getAnchorByText(l_workSheet.getWs_Name())
				.click();

		String l_deleteLink = "Delete this Work Sheet";
		WebAssert.assertLinkPresentWithText(l_currentPage, l_deleteLink);

		// Start deleting page
		webClient.setConfirmHandler(new ConfirmHandler() {
			public boolean handleConfirm(Page page, String message) {
				return false;
			}

		});
		boolean l_isNotConfirmed = webClient.getConfirmHandler().handleConfirm(
				l_currentPage, "Delete this work sheet?");
		assertFalse("Confirm window has not been invoked", l_isNotConfirmed);

		l_currentPage = l_currentPage.getAnchorByText(l_deleteLink).click();

		// Now we should be back in the worksheet details page
		assertEquals("Work Sheet "+l_workSheet.getWs_Name()+" Details",
				l_currentPage.getTitleText());

		// Now let us acknowledge the deletion
		// Start deleting page
		webClient.setConfirmHandler(new ConfirmHandler() {
			public boolean handleConfirm(Page page, String message) {
				return true;
			}

		});

		l_currentPage = l_currentPage.getAnchorByText(l_deleteLink).click();
		// We should now be back at the start page
		WebAssert.assertTitleEquals(l_currentPage, "Welcome to DBExel");
	}

	@Test
	public void testEdit() throws FailingHttpStatusCodeException,
			MalformedURLException, IOException {
		// We will be changing the work sheet name
		String l_thisWorkSheet = "Edit WorkSheet";
		// to the worksheet name
		String l_newWSName = "Edited WorkSheet";

		// Get first page
		HtmlPage l_currentPage = (HtmlPage) webClient.getPage(new URL(FileUtils
				.fetchProperty("dbexel.testsite") + "/DBEXEL/"));

		WorkSheet l_workSheet = fetchTestWorkSheet(l_thisWorkSheet);

		wsDao.createWorkSheet(l_workSheet);

		l_currentPage = (HtmlPage) webClient.getPage(new URL(FileUtils
				.fetchProperty("dbexel.testsite") + "/DBEXEL/"));

		// Check that our newly created link is there
		WebAssert.assertLinkPresentWithText(l_currentPage, l_thisWorkSheet);
		WebAssert.assertLinkNotPresentWithText(l_currentPage, l_newWSName);

		// go to worksheet details
		l_currentPage = l_currentPage.getAnchorByText(l_thisWorkSheet).click();

		assertEquals("Work Sheet " + l_thisWorkSheet + " Details",
				l_currentPage.getTitleText());

		WebAssert.assertLinkPresentWithText(l_currentPage,
				"Edit this Work Sheet");

		// Go to the Edit page
		l_currentPage = l_currentPage.getAnchorByText("Edit this Work Sheet")
				.click();

		WebAssert.assertTitleEquals(l_currentPage, "Update Worksheet");

		// give new name to Work Sheet
		HtmlForm l_currentForm = l_currentPage.getForms().get(0);

		final HtmlTextInput textField = l_currentForm
				.getInputByName("newWSName");

		// Change the value of the text field
		textField.setValueAttribute(l_newWSName);
		// l_currentForm.setAttribute("newWSName",l_newWSName);

		// Submit form
		l_currentPage = DBExelTestTools.getSubmitButton(l_currentForm).click();

		assertEquals("Work Sheet " + l_newWSName + " Details",
				l_currentPage.getTitleText());

		// Go to the start page is the new link present?
		l_currentPage = l_currentPage.getAnchorByText("See the Work Sheets")
				.click();

		WebAssert.assertLinkPresentWithText(l_currentPage, l_newWSName);
		WebAssert.assertLinkNotPresentWithText(l_currentPage, l_thisWorkSheet);

		// Now for the final test
		// Use the new link. Do we go to the expected page?
		l_currentPage = l_currentPage.getAnchorByText(l_newWSName).click();
		assertEquals("Work Sheet " + l_newWSName + " Details",
				l_currentPage.getTitleText());

	}

	@Test
	public void testView() throws FailingHttpStatusCodeException,
			MalformedURLException, IOException {

		WebClient webClient = new WebClient();
		// Get first page
		HtmlPage l_currentPage = (HtmlPage) webClient.getPage(new URL(FileUtils
				.fetchProperty("dbexel.testsite") + "/DBEXEL/"));

		WorkSheet l_workSheet = fetchTestWorkSheet("testView2 WorkSheet");

		wsDao.createWorkSheet(l_workSheet);

		l_currentPage = (HtmlPage) webClient.getPage(new URL(FileUtils
				.fetchProperty("dbexel.testsite") + "/DBEXEL/"));

		// Enter New Worksheet
		l_currentPage = l_currentPage.getAnchorByText(l_workSheet.getWs_Name())
				.click();

		final HtmlTable l_currentTable = (HtmlTable) l_currentPage
				.getElementById("workSheetContentTable");

		// We have one row per entry + 1 column for headers
		assertEquals("1. Wrong number of rows", 3, l_currentTable.getRowCount());

		// We have one column per attribute + 1 column for actions
		assertEquals("1. wrong number of columns", 6, l_currentTable.getRow(0)
				.getCells().size());

	}


	private WorkSheet fetchTestWorkSheet(String in_string) {
		WorkSheet l_workSheet = new WorkSheet(in_string);

		WorkSheet_Attribute l_wsAttr1 = new WorkSheet_Attribute("Column 3");

		WorkSheet_Attribute l_wsAttr2 = new WorkSheet_Attribute("Column 5");

		WorkSheet_Attribute l_wsAttr3 = new WorkSheet_Attribute("Column 7");

		WorkSheet_Attribute l_wsAttr4 = new WorkSheet_Attribute("Column 11");

		WorkSheet_Attribute l_wsAttr5 = new WorkSheet_Attribute("Column 13");

		// Add attributes
		l_workSheet.attachAttribute(l_wsAttr1);
		l_workSheet.attachAttribute(l_wsAttr2);
		l_workSheet.attachAttribute(l_wsAttr3);
		l_workSheet.attachAttribute(l_wsAttr4);
		l_workSheet.attachAttribute(l_wsAttr5);

		// Add Antries
		l_workSheet.addEntry(new WorkSheet_Entry());
		l_workSheet.addEntry(new WorkSheet_Entry());

		// Fill the entries
		l_workSheet
				.getEntries()
				.get(0)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr1, "Attr1 valA"));
		l_workSheet
				.getEntries()
				.get(0)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr2, "Attr2 valB"));
		l_workSheet
				.getEntries()
				.get(0)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr3, "Attr3 valC"));
		l_workSheet
				.getEntries()
				.get(0)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr4, "Attr4 valD"));
		l_workSheet
				.getEntries()
				.get(0)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr5, "Attr5 valE"));

		l_workSheet
				.getEntries()
				.get(1)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr1, "Attr1 valZ"));
		l_workSheet
				.getEntries()
				.get(1)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr2, "Attr2 valY"));
		l_workSheet
				.getEntries()
				.get(1)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr3, "Attr3 valX"));
		l_workSheet
				.getEntries()
				.get(1)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr4, "Attr4 valW"));
		l_workSheet
				.getEntries()
				.get(1)
				.attachAttributeValue(
						new AttributeValue(l_wsAttr5, "Attr5 valV"));

		return l_workSheet;
	}
}
